const std = @import("std");
const jwt = @import("./lib/jwt.zig");
const const_val = @import("../utils/const_value.zig");

pub const GenPayload = struct {
    iss: []const u8,
    sub: []const u8,
    exp: i64,
    username: []const u8,
};

pub const ExpectedPayload = struct {
    iss: []const u8,
    sub: []const u8,
};

pub const ValidatePayload = struct {
    iss: []const u8,
    sub: []const u8,
    exp: i64,
    username: ?[]const u8,
};

/// 生成token函数，默认使用HS256算法
pub fn generateToken(payload: GenPayload) ![]const u8 {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    const token = try jwt.encode(allocator, .HS256, payload, .{ .key = const_val.JWT_SECRET });
    return token;
}

/// 验证token函数
pub fn verifyToken(expected: ExpectedPayload, token: []const u8) !bool {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    var claims_p = jwt.validate(ValidatePayload, allocator, .HS256, token, .{ .key = const_val.JWT_SECRET }) catch {
        // std.debug.print("verifyToken 出错,返回了false\n", .{});
        return false;
    };
    defer claims_p.deinit();

    const claims = claims_p.value;

    if (claims.exp <= 0) return false;
    if (claims.exp < std.time.timestamp()) return false;

    return std.mem.eql(u8, claims.iss, expected.iss) and std.mem.eql(u8, claims.sub, expected.sub);
}

/// 解码token函数
pub fn decodeToken(token: []const u8) !?GenPayload {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    const claims_p = jwt.validate(GenPayload, allocator, .HS256, token, .{ .key = const_val.JWT_SECRET }) catch {
        return null;
    };
    // defer claims_p.deinit();  // 这里不能释放内存

    const claims = claims_p.value;
    return claims;
}
